﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using XGameFrame.Collision;

namespace XGameFrame.Graphic
{
    /// <summary>
    /// Abstract base class for an animated Image
    /// </summary>
    public abstract class AnimatedSpriteBase:CoreGraphicElement
    {

        #region Fields Region
        private int rows;
        private int currentRow;
        private int columns;
        private int currentColumn;
        private int currentFrame;
        private int totalFrames;
        private Vector2 frameSize;
        private float totalTimeElipsed;
        private float animationSpeed;
        protected object value;
        
        #endregion

        #region Properties Region

        /// <summary>
        /// The speed for the Animation
        /// </summary>
        public float AnimationSpeed 
        {
            get { return animationSpeed; }
            set { animationSpeed = value; }
        }
        /// <summary>
        /// The Time elipsed since the object is created
        /// </summary>
        public float TotalTimeElipsed
        {
            get { return totalTimeElipsed; }
            set { totalTimeElipsed = value; }
        }
        /// <summary>
        /// Get the row where the frame is or set it
        /// </summary>
        public int CurrentRow
        {
            get { return currentRow; }
            set { currentRow = value; }
        }
        /// <summary>
        /// Get the column where the frame is or set it
        /// </summary>
        public int CurrentCulumn
        {
            get { return currentColumn; }
            set { currentColumn = value; }
        }

        /// <summary>
        /// Get Size of one frame from the picture or set it
        /// </summary>
        public Vector2 FrameSize
        {
            get { return frameSize; }
            set { frameSize = value; }
        }

        public object Value
        {
            get { return value; }
            set { this.value = value; }
        }
        /// <summary>
        /// Get graphics row count or set it
        /// </summary>
        public int Rows
        {
            get { return rows; }
            set { rows = value; }
        }

        /// <summary>
        /// Get size of one frame or set it
        /// </summary>
        public Vector2 SizeOneFrame
        {
            get { return new Vector2((Size.X / Rows), (Size.Y / Columns)); }
        }

        /// <summary>
        /// Get graphics columns count or set it
        /// </summary>
        public int Columns
        {
            get { return columns; }
            set { columns = value; }
        }

        /// <summary>
        /// Get graphics current frame or set it
        /// </summary>
        public int CurrentFrame
        {
            get { return currentFrame; }
            set { currentFrame = value; }
        }
        /// <summary>
        /// Get graphics total frames count or set it
        /// </summary>
        public int TotalFrames
        {
            get { return totalFrames; }
            set { totalFrames = value; }
        }
        #endregion

        #region Constructor Region
        /// <summary>
        /// Constructor for a new AnimatedSpriteBase with an SpriteAtlas to animate Graphics
        /// </summary>
        /// <param name="pTexture">The Graphic to draw</param>
        /// <param name="pRows">The number of rows</param>
        /// <param name="pColumns">The number of columns</param>
        /// <param name="pPosition">The rectangle around the graphic</param>
        public AnimatedSpriteBase(Texture2D pTexture, int pRows, int pColumns, Vector2 pPosition)
            :base(pTexture,pPosition)
        {
            Rows = pRows;
            Columns = pColumns;
            currentFrame = -1;
            totalFrames = (Rows * Columns) -1;
            FrameSize = new Vector2(Texture.Width / Columns,Texture.Height / Rows);
            Size = new Vector2((float)Texture.Width/Columns, (float)Texture.Height/Rows);

            Bounds = new Rectangle((int)Position.X,
            (int)Position.Y,
            (int)FrameSize.X,
            (int)FrameSize.Y);

            SourceRectangle = new Rectangle(
            (int)FrameSize.X * CurrentCulumn,
            (int)FrameSize.Y * CurrentRow,
            (int)FrameSize.X,
            (int)FrameSize.Y);

            DestRectangle = new Rectangle((int)Position.X,
                (int)Position.Y,
                (int)FrameSize.X,
                (int)FrameSize.Y);
            TotalTimeElipsed = 0;
            AnimationSpeed = 0.05f;
        }

        /// <summary>
        /// Constructor for a new AnimatedSpriteBase with an SpriteAtlas to animate Graphics
        /// </summary>
        /// <param name="pTexture">The Graphic to draw</param>
        /// <param name="pRows">The number of rows</param>
        /// <param name="pColumns">The number of columns</param>
        /// <param name="pPosition">The rectangle around the graphic</param>
        /// <param name="pAnimationSpeed">the speed for the animation</param>
        public AnimatedSpriteBase(Texture2D pTexture, int pRows, int pColumns, Vector2 pPosition,float pAnimationSpeed)
            : base(pTexture, pPosition)
        {
            Rows = pRows;
            Columns = pColumns;
            currentFrame = -1;
            totalFrames = (Rows * Columns) - 1;
            FrameSize = new Vector2(Texture.Width / Columns, Texture.Height / Rows);
            Size = new Vector2((float)Texture.Width / Columns, (float)Texture.Height / Rows);

            Bounds = new Rectangle((int)Position.X,
            (int)Position.Y,
            (int)FrameSize.X,
            (int)FrameSize.Y);

            SourceRectangle = new Rectangle(
            (int)FrameSize.X * CurrentCulumn,
            (int)FrameSize.Y * CurrentRow,
            (int)FrameSize.X,
            (int)FrameSize.Y);

            DestRectangle = new Rectangle((int)Position.X,
                (int)Position.Y,
                (int)FrameSize.X,
                (int)FrameSize.Y);
            TotalTimeElipsed = 0;
            AnimationSpeed = pAnimationSpeed;
        } 
        #endregion


        #region Methods
        
        /// <summary>
        /// To start the animation
        /// </summary>
        public void Play()
        {
            this.AnimationPaused = false;
        }
        /// <summary>
        /// To stop the animation
        /// </summary>
        public void Stop()
        {
            this.AnimationPaused = true;
        }

        #endregion

        #region Abstract Methods
        /// <summary>
        /// Do Logic for AnimatedSprites
        /// </summary>
        public virtual void Update(GameTime pGameTime)
        {
            TotalTimeElipsed += (float)pGameTime.ElapsedGameTime.TotalSeconds;
            if (TotalTimeElipsed > AnimationSpeed)
            {
                TotalTimeElipsed -= AnimationSpeed;
                if (!AnimationPaused)
                {
                    if (CurrentFrame == TotalFrames)
                    {
                        CurrentFrame = 0;
                        CurrentCulumn = 0;
                        CurrentRow = 0;

                    }
                    else
                    {
                        CurrentFrame++;
                        CurrentCulumn = CurrentFrame % Columns;
                        if (CurrentFrame % Columns == 0 && CurrentFrame > 0)
                            CurrentRow++;
                    }
                }
            }
            //UpdateBoundPositions();
            base.CheckAllCollisions();
        }

        /// <summary>
        /// Do drawings for AnimatedSprites
        /// </summary>
        /// <param name="pSpriteBatch">The graphic to draw</param>
        public abstract void Draw(SpriteBatch pSpriteBatch);
        /// <summary>
        /// Do logic if the element is Hover
        /// </summary>
        /// <param name="pPlayerIndex">normally the player how has hoverd the element</param>
        public abstract void OnHover(PlayerIndex pPlayerIndex);

        public abstract void HandleInput(PlayerIndex pPlayerIndex);

        #endregion

        
    }
}
